import {DataRouter} from "../frame/dataSource/DataRouter";
import {AbilityController} from "../controller/AbilityController";
import {ItemType} from "../frame/dataSource/DataModel";
import {
    BroadcastRequest,
    BroadcastType,
    ControllerNo,
    GuiControllerOpt,
    GuiId
} from "../controller/model/ControllerOpt";
import {ControllerBroadcast} from "../controller/ControllerBroadcast";
import Configer from "../frame/apiModel/config/Configer";
import {ConfigKey} from "../constant/ConfigConstant";
import {GlobalEnv} from "../utils/GlobalEnv";
import {Logger} from "../frame/apiModel/config/Logger";
import {TriggerFactory} from "../frame/TriggerFactory";
import {UnitModel} from "../frame/apiModel/adapterModel/model3/UnitModel";
import {ItemModel} from "../frame/apiModel/adapterModel/model3/ItemModel";
import {PlayerModel} from "../frame/apiModel/adapterModel/model4/PlayerModel";
import {PlayerFactory} from "../frame/PlayerFactory";
import {ModelFactory} from "../frame/apiModel/adapterModel/model5/ModelFactory";
import {GuiController, OptType} from "../controller/GuiController";
import {TaskController} from "../controller/TaskController";
import {CodeUtil} from "../frame/codeAdapter/CodeUtil";
import {UnitController} from "../controller/UnitController";
import {DataRouterUtil} from "../utils/router/DataRouterUtil";
import {GoodController} from "../controller/GoodController";
import {AbilityUtil} from "./ability/AbilityUtil";
import {ChangeUnitType} from "../type/Type";
import {ItemDataKey} from "../frame/dataSource/DataSource";
import {FinalKey} from "../constant/FinalConstant";

export function useItemTrigger() {
    // todo 【需要被回退】
    const useItem = function (this: void, getUnit: UnitModel, item: ItemModel, activePlayer: PlayerModel) {
        const cd = item.data[ItemDataKey.coolDown];
        if (cd && cd > 0) {
            Logger.toastError("物品冷却中", activePlayer);
            return;
        }
        const ret = useItemCallBack(getUnit, item, activePlayer);
        if (ret) {
            const useInterval = item.template.useInterval;
            if (!CodeUtil.isNullOrZero(useInterval)) {
                item.data[ItemDataKey.coolDown] = useInterval;
            }
        }
    }
    TriggerFactory.getInstance().registerUnitUseItem(useItem)
    // TriggerFactory.getInstance().registTrigger(TriggerKey.useItem, useItem)
}

export function useItemCallBack(this: void, getUnit: UnitModel, item: ItemModel, activePlayer: PlayerModel, seller?: UnitModel) {
    if (item) {
    } else {
        return false;
    }

    const itemJson = item.getJson();

    const itemIdStr = item.strId;
    const itemData = DataRouter.getItemDataByItemId(itemIdStr);
    let success = TaskController.getInstance().itemCheckConditions(getUnit, activePlayer, itemIdStr);
    if (itemData) {
    } else {
        return false;
    }
    if (success) {
        const useByTypeRet = useItemByType(getUnit, item, activePlayer, seller);
        const bConsumeByType = useByTypeRet.bConsume;
        const successByType = useByTypeRet.success;

        success = successByType;


        if (success) {
            const useByIdRet = useItemById(getUnit, item);
            const successById = useByIdRet.success;

            success = successById;
        }

        if (bConsumeByType) {
            // const itemUseNum = item.charges;
            // if (itemUseNum > 1) {
            //     item.charges = item.charges - 1;
            // } else {
            //     ModelFactory.getInstance().unitRemoveItem(getUnit, item);
            // }
        }
    }
    if (success) {
        const successTip = itemData.successTip;
        if (successTip) {
            Logger.toastProduct(successTip, activePlayer)
        }
        return true;
    } else {
        const failedTip = itemData.failedTip;
        if (failedTip) {
            Logger.toastProduct(failedTip, activePlayer)
        }
        const failedReturn = itemData.failedReturn;
        if (!CodeUtil.isNullOrZero(failedReturn)) {
            ModelFactory.getInstance().createItemInUnit(itemJson, getUnit);
        }
        return false;
    }
}

export function useItemById(useUnit: UnitModel, item: ItemModel): { success: boolean }  {
    let bConsume = false;
    let success = true;
    const player = PlayerFactory.getInstance().getUnitOwner(useUnit);
    const chooseLoseAbility = Configer.getFinal(FinalKey.chooseLoseAbility) as string;
    const sealItemId = Configer.getFinal(FinalKey.sealItemId) as string;
    const callBoss = Configer.getFinal(FinalKey.callBoss) as string;
    const itemId = item.strId;
    switch (itemId) {
        case chooseLoseAbility: {
            useLoseAbility(useUnit);
            break;
        }
        case sealItemId: {
            const unitJson = item.data[ItemDataKey.sealData];
            if (unitJson) {
                success = UnitController.getInstance().addPet(player, unitJson, false)
            }
            break;
        }
        case callBoss:{
            const success = TaskController.getInstance().itemCheckConditions(useUnit, player, itemId);
            if (success) {
                const wave = GlobalEnv.wave;
                // MonsterUtil.createAttackBoss(wave);
            } else {
                Logger.toastProduct('无法重复召唤Boss', player)
            }
            break;
        }
    }
    return { success };
}



export function useLoseAbility(useUnit: UnitModel) {
    const player = PlayerFactory.getInstance().getUnitOwner(useUnit);
    const fun = () => {
        const req: BroadcastRequest = { controllerNo: ControllerNo.StoreController, broadcastType: BroadcastType.addStoreTask, data: { player, no: ControllerNo.AbilityController } }
        ControllerBroadcast.getInstance().broadcast(req);
    }
    AbilityController.getInstance().chooseLoseAbility(useUnit, fun)
}


export function useItemByType(useUnit: UnitModel, item: ItemModel, activePlayer: PlayerModel, seller?: UnitModel): { bConsume: boolean, success: boolean } {
    let bConsume = false;
    let success = true;
    const itemIdStr = item.strId;
    const itemData = DataRouter.getItemDataByItemId(itemIdStr);
    if (itemData) {
        const itemType = itemData.item_type;

        switch (itemType) {
            case ItemType.ability:
                bConsume = true
                success = useAbilityItem(useUnit, item);
                break;
            case ItemType.rewardBox:
                bConsume = true
                success = TaskController.getInstance().useRewardsItem(useUnit, itemIdStr);
                break;
            case ItemType.uiChooseItemBox:
                bConsume = true
                const ownerId = useUnit.getHandleId();
                const opt = new GuiControllerOpt(GuiId.chooseItemBar, { itemId: itemIdStr, ownerId });
                GuiController.getInstance().showGui(opt, activePlayer, OptType.open);
                break;
            case ItemType.task:
                bConsume = true;
                success = getTaskItem(activePlayer, itemIdStr);
                break;
            case ItemType.trans:
                bConsume = true;
                success = useTransItem(useUnit, itemIdStr);
                break;
            case ItemType.recordItem:
                bConsume = true;
                success = getRecordItem(useUnit, activePlayer, item);
                break;
            case ItemType.build:
                bConsume = getItemToEat(useUnit, item);
                break;
            case ItemType.seller:
                if (seller) {
                    bConsume = true;
                    success = TaskController.getInstance().useRewardsItem(seller, itemIdStr);
                }
                break;
        }
    }
    return { bConsume: bConsume, success };
}

export function useTransItem(useUnit: UnitModel, itemId: string) {
    const itemData = DataRouter.getItemDataByItemId(itemId);
    const tansId = itemData?.type_id;
    const player = PlayerFactory.getInstance().getUnitOwner(useUnit);

    if (tansId) {
        const transData = DataRouter.getTransDataByTransId(tansId);
        UnitController.getInstance().useTransData([useUnit], transData);
    } else {
        Logger.toastError('没有找到对应的传送设置');
    }
    return false;
}

export function getTaskItem(player: PlayerModel, itemId: string) {
    const itemData = DataRouter.getItemDataByItemId(itemId);
    const taskId = itemData?.type_id;
    if (taskId) {
        return TaskController.getInstance().applyTask(player, taskId);
    }
    return false;
}

function getRecordItem (unit: UnitModel, player: PlayerModel, item: ItemModel) {
    const bMonster = UnitController.unitItem_generateData_Map.has(item);
    if (bMonster) {
        const itemStr = DataRouterUtil.getItemStr(item.strId);
        if (itemStr) {
            TaskController.getInstance().recordNum(player, itemStr);
            const monsterData = UnitController.unitItem_generateData_Map.get(item);
            UnitController.getInstance().clearGenerateData(item);
            UnitController.getInstance().checkToInitMonster(monsterData, 1, true);
        }
    }
    ModelFactory.getInstance().unitRemoveItem(unit, item);
    return true;
}

function getItemToEat(useUnit: UnitModel, item: ItemModel) {
    const itemId = item.strId;

    const unitId = useUnit.strId;

    const itemData = DataRouter.getItemDataByItemId(itemId);

    let familyType = '';

    const unitData = DataRouter.getUnitDataByUnitId(unitId);

    if (unitData) {
        familyType = unitData.family_tpye;
    }

    const abilList = itemData?.abilList;
    const abilListArr = CodeUtil.getArrBySplit(abilList);
    let bEat = false;
    for (let i = 0; i < abilListArr.length; i++) {
        const abilityId = abilListArr[i];
        const abilityData = DataRouter.getAbilityDataById(abilityId);
        if (abilityData) {
            const buildUnitId = abilityData.UnitID;
            const unitDataTemp = DataRouter.getUnitDataByUnitId(buildUnitId);
            if (unitDataTemp) {
                const tempFamilyType = unitDataTemp.family_tpye;
                if (tempFamilyType === familyType) {
                    bEat = true;
                    break;
                }
            }
        }
    }
    if (bEat) {
        const nextUnitId = AbilityUtil.eatAUnit(useUnit, 1);
        if (nextUnitId) {
            Logger.toastError(`吃物品了 ${item.getHandleId()}`)
            GoodController.getInstance().removeGoods(useUnit, item);
            UnitController.getInstance().itemDeadRemove(item);
            UnitController.getInstance().changeUnit(useUnit, nextUnitId, ChangeUnitType.other);
        } else {
            bEat = false;
        }
    }
    return bEat
}

function useAbilityItem(useUnit: UnitModel, item: ItemModel) {
    const itemIdStr = item.strId;
    const player = PlayerFactory.getInstance().getUnitOwner(useUnit);
    const itemData = DataRouter.getItemDataByItemId(itemIdStr);
    if (itemData) {
    } else {
        Logger.toastError('使用技能书失败, 因为没有对应物品消息');
        return false;
    }
    const abilityId = itemData.type_id;
    const isHero = GlobalEnv.isInHeroGroup(useUnit);
    if (isHero) {
    } else {
        Logger.toastProduct(`只有英雄可以使用技能书`, player)
        return false;
    }
    if (abilityId) {
        const learnSkillByFamilyId: number = Configer.getConfig(ConfigKey.learnSkillByFamilyId);
        let ret;
        if (!CodeUtil.isNullOrZero(learnSkillByFamilyId)) {
            const familyId = abilityId;
            const familyLv = itemData.type_num;
            ret = AbilityController.getInstance().learnAbilityByFamilyIdCheck(useUnit, familyId, familyLv);
        } else {
            ret = AbilityController.getInstance().learnAbilityCheck(useUnit, abilityId);
        }
        if (ret) {
            const req: BroadcastRequest = { controllerNo: ControllerNo.StoreController, broadcastType: BroadcastType.addStoreTask, data: { player, no: ControllerNo.AbilityController } }
            ControllerBroadcast.getInstance().broadcast(req);
            return true
        } else {
            // const loc = useUnit.loc;
            // ModelFactory.getInstance().createItemInPoint(itemJson, loc);
            return false;
        }
    } else {
        Logger.toastError('沒有找到与物品对应的技能');
        return false;
    }
}
